考虑用静态工厂方法代替构造器
创建类实例的方法
- 公有构造器
- 公有静态工厂方法
静态工厂方法与构造器相比的优势
静态工厂方法有名称
如果构造器的参数本身没有确切的描述正被返回的对象,那么具有适当名称的静态工厂会更容易使用,举个例子,构造器
BigInteger(int, int, Random)
返回的BigInteger可能为素数,如果用名为BigInteger.probablePrime的静态工厂方法来表示,显然更加清楚。另外,当一个类需要多个带有相同签名的构造器时,就用静态工厂方法代替构造器。
不必在每次调用它们的时候都创建一个新对象
可以返回原返回类型的任何子类型的对象
在创建参数化类型实例的时候,它们使代码变得更加简洁
在调用参数化类的构造器时,即使类型参数很明显,也必须指明,这通常要求你接连两次提供类型参数:
1Map<String, List<String>> m = new HashMap<String, List<String>>();随着类型参数变得越来越长,越来越复杂,这显然是不合适的。但是有了静态工厂方法,编译器就可以替你找到类型参数,这就是类型推导:
123public static <K, V> HashMap<K, V> newInstance() {return new HashMap<K, V>();}你就可以用下面简洁的代码代替上面这段繁琐的声明:
1Map<String, List<String>> m = HashMap.newInstance();
静态工厂方法的一些惯用名称
valueOf
该方法返回的实例与它的参数具有相同的值,这样的静态工厂方法实际上是类型转换方法
of
valueOf的一种更加简洁的替代
getInstance
返回的实例是通过方法的参数来描述的,但是不能够说与参数具有相同的值,对于Singleton来说,该方法没有参数,并返回唯一的实例
newInstance
与getInstance实例一样,但newInstance能够确保返回的每个实例都与所有其他实例不同
遇到多个构造器参数时要考虑用构建器
当构造器参数很多时,重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难写,并且难以阅读。如果读者想知道那些值是什么意思,必须很仔细的数着这些参数来一探究竟,更为可怕的是,一长串相同类型的参数会导致一些微妙的错误,如果客户端不小心颠倒了其中两个参数的顺序,编译器并不会报错,但是在程序运行的时候会出现错误,这种错误往往还比较难以发现。
遇到许多构造器参数的时候,还可以使用JavaBeans模式,在这种模式下,调用一个无参构造器来创建对象,然后调用setter方法来设置每个必要的参数。JavaBeans模式最大的问题就是阻止了把类做成不可变的可能,需要程序员付出额外的努力来确保它的线程安全。
对于多个构造器参数还有第三种方法,即Builder模式。我们先看代码:
|
|
注意NutritionFacts是不可变的,下面是客户端代码:
|
|
如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数可选的时候。